LoginSignup
251
258

More than 1 year has passed since last update.

【画像で説明】DockerでAnaconda環境をつくり、コンテナの中でVSCodeを使う

Last updated at Posted at 2019-06-28

やること

  1. 公式のAnacondaイメージをベースに自前のイメージをつくります。
  2. コンテナを立ち上げ、Jupyter Labを起動します。
  3. ブラウザから、コンテナ内で立ち上げたJupyter Labを操作します。
  4. VSCodeでコンテナに接続します。
  5. VSCodeからもコンテナ内部を編集できることを確認します。

なにがうれしいの??

  • Anacondaをホストマシンにインストールすることのリスク回避(Homebrewやpipとの衝突)
  • 複数人で開発環境を共有できる

環境

  • MacOS X 10.14.5 (Mojave)
  • VSCode 1.35.1
  • Docker 18.09.2

Dockerイメージをつくる

Dockerfile

Anaconda公式イメージをベースにします。
https://hub.docker.com/r/continuumio/anaconda3


# ベースイメージ名:タグ名
FROM continuumio/anaconda3:2019.03

# pipをアップグレードし必要なパッケージをインストール
RUN pip install --upgrade pip && \
    pip install autopep8 && \
    pip install Keras && \
    pip install tensorflow 

# コンテナ側のルート直下にworkdir/(任意)という名前の作業ディレクトリを作り移動する
WORKDIR /workdir

# コンテナ側のリッスンポート番号
# 明示しているだけで、なくても動く
EXPOSE 8888

# ENTRYPOINT命令はコンテナ起動時に実行するコマンドを指定(基本docker runの時に上書きしないもの)
# "jupyter-lab" => jupyter-lab立ち上げコマンド
# "--ip=0.0.0.0" => ip制限なし
# "--port=8888" => EXPOSE命令で書いたポート番号と合わせる
# ”--no-browser” => ブラウザを立ち上げない。コンテナ側にはブラウザがないので 。
# "--allow-root" => rootユーザーの許可。セキュリティ的には良くないので、自分で使うときだけ。
# "--NotebookApp.token=''" => トークンなしで起動許可。これもセキュリティ的には良くない。
ENTRYPOINT ["jupyter-lab", "--ip=0.0.0.0", "--port=8888", "--no-browser", "--allow-root", "--NotebookApp.token=''"]

# CMD命令はコンテナ起動時に実行するコマンドを指定(docker runの時に上書きする可能性のあるもの)
# "--notebook-dir=/workdir" => Jupyter Labのルートとなるディレクトリを指定
CMD ["--notebook-dir=/workdir"]

イメージビルド

Dockerfileが置いてあるディレクトリで以下を実行

docker build -t ANATA_NO_IMAGE_NAME .

-t

ビルドしたイメージに名前(:タグ名)をつけるオプションです。

. (最後のドット)

ビルドコンテキストの指定。
Dockerfileのあるディレクトリを指定します。
ここでは.なのでカレントディレクトリを指定しています。
docker buildコマンドではビルドコンテキスト内にあるDockerfileを自動で読みにいきます。

コンテナ起動

① docker runコマンドで起動する場合

docker run -it \
-p 8080:8888 \
--rm \
--name ANATA_NO_CONTAINER_NAME(任意) \ 
--mount type=bind,src=`pwd`,dst=/workdir  \
ANATA_NO_IMAGE_NAME(上でビルドしたもの)

このコマンド何してるの??

docker run

docker pulldocker createdocker start を1発で行うやつ。
イメージがホストマシン上になければDocker Hubからpullしてきて、コンテナつくって、コンテナを起動します。

-it

-i-tをまとめて書いてるものです。

  • -i or --interactive
    => ホスト側のシェルからコンテナ内を操作できるようにする。

  • -t or --tty
    => 仮想ttyの割当て。キーバインドを使用したり、色を出力したりシェル操作を便利に行うために指定。

こちらが非常にわかりやすいです。
https://teratail.com/questions/121780
https://teratail.com/questions/19477
https://teratail.com/questions/100044

-p 8080:8888

ホスト側のポート番号:コンテナ側のポート番号 をひも付けます。
ローカルのブラウザからlocalhost:8080でコンテナ内で立ち上げたjupyterをひらけるように。

--rm

コンテナを停止したときに自動で削除(docker rm)までしてくれます。

--name ANATA_NO_CONTAINER_NAME

任意のコンテナ名をつける。
なくても動きます。
これを指定しない場合、自動でコンテナ名が付与されます。

--mount type=bind,src=`pwd`,dst=/workdir

ホスト側のディレクトリとコンテナ側のディレクトリを同期させる。

  • type=bind => マウントタイプにbindを指定(他にvolume,tmpfsの指定が可能)
  • src=`pwd` => ホスト側のディレクトリにカレントディレクトリを指定(任意のディレクトリでOK)
  • dst=/workdir => コンテナ側のディレクトリにルート直下のworkdir/を指定(任意のディレクトリでOK)

-v でも --mountと同じことができます。

  • -v => ホスト側に存在しないディレクトリをマウントしようとすると新規作成
  • --mount => ホスト側に存在しないディレクトリをマウントしようとするとエラー

--mount を使った方が誤って空のディレクトリをマウントしてしまう事故などを防げます。

例えば空のディレクトリをマウントしてしまうと、必要なファイルが覆い隠されてしまうためコンテナが正常に動作しなくなる場合がある。
(見た目上は上書きされたように見えるが、マウント元のディレクトリの中身でマウント先のディレクトリの中身が隠れているだけで削除されるわけではない)

公式でも以下のように --mount オプションでの書き方が推奨されているようです。

ヒント: はじめて利用する方は --mount を利用してください。 上級ユーザーは -v や --volume を用いることに慣れているかもしれませんが、--mount を利用するように心がけてください。 --mount の方が簡単に利用することができるとの調査もあります。

ANATA_NO_IMAGE_NAME

先程docker buildで作ったイメージ名を指定します。

② docker-composeで起動する場合

上記docker run 〜コマンドをコード化したようなものです。

docker-compose.yml

docker-compose.yml
version: '3' # docker-composeファイルの書式バージョン。最新の’3’を指定(2019/6/27現在)
services:
  dev: # 任意の名前(ディレクトリ名 + dev がコンテナ名となります)
    build:
      context: .
      dockerfile: Dockerfile
    image: ANATA_NO_IMAGE_NAME
    ports:
    - "8080:8888"
    volumes:
    - .:/workdir

コンテナ起動

docker-compose.ymlが置いてあるディレクトリで以下を実行

docker-compose up

Jupyter Labを開く

ブラウザのアドレスバーに localhost:8080 を入力しEnter。
=> Jupyter Labが開きます。マウントさせたディレクトリと同じものが入っていればOK。

同期されるか確認

ローカルのディレクトリで新しくファイルを作ってみます。

touch test.ipynb

再読込ボタンでJupyter Labのエクスプローラを更新して、test.ipynb が追加されていれば成功です。

コンテナ停止

docker runで起動した場合

docker stop ANATA_NO_CONTAINER_NAME

docker-compose up で起動した場合

docker-compose stop

コンテナ削除

docker runで起動した場合

docker rm ANATA_NO_CONTAINER_NAME

docker-compose up で起動した場合

docker-compose down

コンテナの中でもVSCodeつかいたい人

:raised_hand:

拡張機能のインストール

表示 > コマンドパレット > 拡張と打つ > ビュー:拡張機能を表示する
スクリーンショット 2019-06-24 10.34.41.png

サイドバーの入力欄にremote と打つ > Remote - Containersを選択 > インストール

スクリーンショット 2019-06-28 11.26.11.png

これが出てくればOK
スクリーンショット 2019-06-28 11.32.01.png

もう一回コンテナ起動

  • コンテナ名 => test_container
  • 使用イメージ => anaconda_test_image

として起動してみます。

docker run -it -p 8080:8888 --name test_container \ 
--mount type=bind,src=`pwd`,dst=/workdir anaconda_test_image

コンテナに接続

左下のボタンを押して、
Remote - Containers: Attach to Running Container…を選択

スクリーンショット 2019-06-28 12.26.18.png

起動中のコンテナ一覧が出てくるので、接続したいコンテナを選択します。

スクリーンショット 2019-06-28 13.00.03.png

新しいウィンドウが開きます。

左下のボタンがAttached Container ~となります。
スクリーンショット 2019-06-28 13.02.39.png

以下の手順で、マウント先(コンテナ側)のディレクトリを選択します。

スクリーンショット 2019-06-28 13.03.45.png

マウント元(ホスト側)のディレクトリと同じ内容が表示されればOK。

スクリーンショット 2019-06-28 13.55.58.png

Jupyterで新規ファイル作成してみます。
Untitled.ipynbがVSCode側にも即反映されるのが確認できるかと思います。

スクリーンショット 2019-06-28 13.51.52.png

コンテナ側に拡張機能インストール

ローカルでVSCodeにインストールされている一部の拡張機能が、コンテナ側には入っていません。
必要に応じでインストールします。

スクリーンショット 2019-06-28 14.13.40.png

最後に

ここまで読んで頂きありがとうございました。
VSCodeでJupyterのように実行結果を表示させる方法も書いたので、もしよろしければ。
=> 【画像で説明】VSCodeをJupyter化する

参照

ありがとうございました!

251
258
7

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
251
258